package com.freexiaoyu.cloud.service

import android.os.StatFs
import android.text.TextUtils

import com.freexiaoyu.cloud.CloudApplication
import com.freexiaoyu.cloud.utils.AppConfig
import com.freexiaoyu.cloud.utils.NetUtil

import java.io.File
import java.io.IOException
import java.util.logging.Logger

import okhttp3.Cache
import okhttp3.CacheControl
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory

/**
 * Created by DIY on 2017/04/17
 * author:free宇
 * email:freexiaoyu@foxmail.com
 * describe:
 */

object BuildService {
    private var retrofit: Retrofit? = null

    //设置Base的访问路径
    //字符串
    //请求的结果转为实体类
    //.addConverterFactory(GsonConverterFactory.create())
    val cloud: ApiService
        get() {
            if (retrofit == null) {
                retrofit = Retrofit.Builder()
                        .baseUrl(AppConfig.HOT_URL)
                        .client(defaultOkHttpClient)
                        .addConverterFactory(ScalarsConverterFactory.create())
                        .addConverterFactory(GsonDConverterFactory.create())
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .build()
            }
            return retrofit!!.create(ApiService::class.java)
        }

    /**这个方法获取显示图片明显没有上面的client快 */
    var defaultOkHttpClient = OkHttpClient.Builder()
            .addInterceptor(LoggingInterceptor())
            .addInterceptor(CacheControlInterceptor())
            .addInterceptor(QueryParameterInterceptor())
            .addNetworkInterceptor(CacheControlInterceptor())
            //.cookieJar(new CookiesManager())//增加cookie
            .cache(cache)
            .build()

    private val cache: Cache
        get() {
            val file = File(CloudApplication.instance().cacheDir, "GlobalCache")
            return Cache(file, calculateDiskCacheSize(file))
        }


    //公共参数
    class QueryParameterInterceptor : Interceptor {
        @Throws(IOException::class)
        override fun intercept(chain: Interceptor.Chain): Response {
            val originalRequest = chain.request()
            val request: Request
            val method = originalRequest.method
            val headers = originalRequest.headers
            val modifiedUrl = originalRequest.url.newBuilder()
                    // Provide your custom parameter here
                    .addQueryParameter("platform", "android")
                    .addQueryParameter("ver", AppConfig.VER)
                    .build()
            request = originalRequest.newBuilder().url(modifiedUrl).build()
            return chain.proceed(request)
        }
    }


    class CacheControlInterceptor : Interceptor {
        @Throws(IOException::class)
        override fun intercept(chain: Interceptor.Chain): Response {

            var request = chain.request()
            val cacheControl = request.cacheControl.toString()

            // 无网络时加载缓存
            if (!NetUtil.isNetworkAvailable(CloudApplication.instance())) {
                if (!TextUtils.isEmpty(cacheControl)) {
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build()

                    val originalResponse = chain.proceed(request)

                    return originalResponse.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=2419200")
                            .removeHeader("Pragma")
                            .build()
                } else {
                    return chain.proceed(request)
                }


            } else {
                val originalResponse = chain.proceed(request)

                return if (cacheControl != null && cacheControl.length != 0) {
                    // 获取请求头的缓存设置，直接设置到响应头中
                    // 这样就可以通过设置请求头来缓存内容
                    originalResponse.newBuilder()
                            .header("Cache-Control", cacheControl)
                            .removeHeader("Pragma")
                            .build()
                } else {
                    // 对于图片，不作处理
                    originalResponse
                }
            }
        }
    }

    class LoggingInterceptor : Interceptor {
        @Throws(IOException::class)
        override fun intercept(chain: Interceptor.Chain): Response {
            //这个chain里面包含了request和response，所以你要什么都可以从这里拿
            val request = chain.request()
            val t1 = System.nanoTime()//请求发起的时间
            Logger.getAnonymousLogger().info(String.format("发送请求 %s on %s%n%s",
                    request.url, chain.connection(), request.headers))
            val response = chain.proceed(request)
            val t2 = System.nanoTime()//收到响应的时间
            //这里不能直接使用response.body().string()的方式输出日志
            //因为response.body().string()之后，response中的流会被关闭，程序会报错，我们需要创建出一
            //个新的response给应用层处理
            val responseBody = response.peekBody((1024 * 1024).toLong())
            Logger.getAnonymousLogger().info(String.format("接收响应: [%s] %n返回json:【%s】 %.1fms%n%s",
                    response.request.url,
                    responseBody.string(),
                    (t2 - t1) / 1e6,
                    response.headers))

            return response
        }
    }

    /**
     * This is copied from Picasso
     */
    private fun calculateDiskCacheSize(dir: File): Long {
        var size = (5 * 1024 * 1024).toLong()
        try {
            val statFs = StatFs(dir.absolutePath)
            val available = statFs.blockCount.toLong() * statFs.blockSize
            size = available / 50
        } catch (ignored: IllegalArgumentException) {

        }

        // Bound inside min/max size for disk cache.
        return Math.max(Math.min(size, (50 * 1024 * 1024).toLong()), (5 * 1024 * 1024).toLong())
    }
}
